package raft

// 日志的逻辑结构体，不是实际上的日志
type Logs struct {
	// 实际的日志列表
	Entries []LogEntry
}

// LogEntry
type LogEntry struct {
	// 命令
	Command CommandEntry
	// 产生该日志时的任期
	Term int64
	// 产生该日志时日志的索引
	Index int64 //Index代表LogEntry在Logs的Entries数组的索引
}

// 将新的日志（列表）拼接到当前日志列表中
func (l *Logs) append(entries ...LogEntry) {
	l.Entries = append(l.Entries, entries...)
}

// 创建一个日志列表为空的日志对象
func MakeEmptyLog() *Logs {
	log := Logs{
		Entries: make([]LogEntry, 0),
	}
	return &log
}

// 返回idx所表示的日志
func (l *Logs) at(idx int64) *LogEntry {
	return &l.Entries[idx]
}

// 返回idx之前的日志子集
func (l *Logs) truncate(idx int64) {
	l.Entries = l.Entries[:idx]
}

// 返回idx之后的日志子集
func (l *Logs) slice(idx int64) []LogEntry {
	return l.Entries[idx:]
}

// 返回日志列表的长度
func (l *Logs) len() int64 {
	return int64(len(l.Entries))
}

// 返回最后一个日志
func (l *Logs) lastLog() *LogEntry {
	if l.len() > 0 {
		return l.at(int64(l.len()) - 1)
	} else {
		return new(LogEntry)
	}
}

// 返回term所表示的最后一个日志的索引
func (l *Logs) findLastLogIndexByTerm(term int64) int64 {
	for i := l.lastLog().Index; i > 0; i-- {
		if l.at(i).Term == term {
			return i
		} else if l.at(i).Term < term {
			break
		}
	}
	return -1
}
